package com.itheima.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.itheima.dao.AdminMapper;
import com.itheima.dao.CategoryMenuMapper;
import com.itheima.dao.RoleMapper;
import com.itheima.pojo.Admin;
import com.itheima.pojo.CategoryMenu;
import com.itheima.pojo.Role;
import com.itheima.service.AdminService;
import com.itheima.utils.CheckUtils;
import com.itheima.utils.IdWorker;
import com.sun.org.apache.bcel.internal.generic.I2F;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class AdminServiceImpl implements AdminService {

    @Autowired
    private AdminMapper adminMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private CategoryMenuMapper categoryMenuMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Override
    public Admin findByUsername(String username) {
        Example example = new Example(Admin.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("userName", username);
        Admin admin = adminMapper.selectOneByExample(example);
        return admin;
    }

    @Override
    public Map<String, Object> getMenu(String uid) {
        Admin admin = adminMapper.selectByPrimaryKey(uid);
        //通过角色获取管辖的菜单uid
        Role role = roleMapper.selectByPrimaryKey(admin.getRoleUid());
        if (role == null) {
            throw new RuntimeException("角色不存在!");
        }
        String categoryMenuUids = role.getCategoryMenuUids();
        List<String> menuIdList = JSON.parseArray(categoryMenuUids, String.class);

        //1级菜单
        List<CategoryMenu> parentList = new ArrayList<>();
        //2级菜单
        List<CategoryMenu> sonList = new ArrayList<>();
        //3级菜单
        List<CategoryMenu> buttonList = new ArrayList<>();
        menuIdList.forEach(menuId -> {
            CategoryMenu categoryMenu = categoryMenuMapper.selectByPrimaryKey(menuId);
            switch (categoryMenu.getMenuLevel()) {
                case 1:
                    parentList.add(categoryMenu);
                    break;
                case 2:
                    sonList.add(categoryMenu);
                    break;
                case 3:
                    buttonList.add(categoryMenu);
                    break;
            }
        });
        Map<String, Object> resultMap = new HashMap();
        resultMap.put("parentList", parentList);
        resultMap.put("sonList", sonList);
        resultMap.put("buttonList", buttonList);
        return resultMap;
    }

    @Override
    public Map<String, Object> getInfo(String uid) {
        Admin admin = adminMapper.selectByPrimaryKey(uid);
        if (admin == null) {
            throw new RuntimeException("用户不存在!");
        }
        //通过admin获取role相关信息
        Role role = roleMapper.selectByPrimaryKey(admin.getRoleUid());
        if (role == null) {
            throw new RuntimeException("角色不存在!");
        }
        List<Role> roles = new ArrayList<>();
        roles.add(role);
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("roles", roles);
        resultMap.put("avatar", admin.getAvatar());
        return resultMap;
    }

    @Override
    @Transactional
    public void updateLastLogin(Admin admin, String ip) {
        admin.setLoginCount(admin.getLoginCount() + 1);
        admin.setLastLoginTime(new Date());
        admin.setLastLoginIp(ip);
        admin.setUpdateTime(new Date());
        adminMapper.updateByPrimaryKey(admin);
    }

    /**
     * 注册功能
     *
     * @param assignbody
     * @param ipAddr
     */
    @Override
    @Transactional
    public void register(Map assignbody, String ipAddr) {
        if (assignbody == null) {
            throw new RuntimeException("请输入注册信息");
        }
        //判断手机号输入是否正确
        if (assignbody.get("mobile") == null || "".equals(assignbody.get("mobile")) || !CheckUtils.checkMobileNumber(assignbody.get("mobile").toString())) {
            throw new RuntimeException("手机号格式有误!");
        }
        //判断邮箱输入是否正确
        if (assignbody.get("email") == null || "".equals(assignbody.get("email")) || !CheckUtils.checkEmail(assignbody.get("email").toString())) {
            throw new RuntimeException("邮箱格式有误!");
        }
        //根据手机号获取redis中的验证码
        Object code = redisTemplate.boundValueOps("register_code_" + assignbody.get("mobile").toString()).get();
        if (assignbody.get("validCode") == null || "".equals(assignbody.get("validCode")) || code == null || "".equals(code) || !code.equals(assignbody.get("validCode"))) {
            throw new RuntimeException("验证码过期或输入错误!");
        }
        //判断用户名是否唯一,系统有相同的用户名不可注册
        if (assignbody.get("userName") == null || "".equals(assignbody.get("userName"))) {
            throw new RuntimeException("用户名不能为空!");
        }
        Example example = new Example(Admin.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("userName", assignbody.get("userName"));
        int count = adminMapper.selectCountByExample(example);
        if (count > 0) {
            throw new RuntimeException("用户名已存在!");
        }
        //将注册数据中的admin数据封装成对象
        Admin admin = JSON.parseObject(JSON.toJSONString(assignbody), Admin.class);
        //将admin信息存入到数据库
        admin.setUid(idWorker.nextId() + "");
        admin.setLastLoginIp(ipAddr);
        admin.setLastLoginTime(new Date());
        admin.setCreateTime(new Date());
        admin.setUpdateTime(new Date());
        admin.setLoginCount((long) 0);  //登录次数为0
        //将密码以密文形式存入
        admin.setPassWord(bCryptPasswordEncoder.encode(admin.getPassWord()));
        adminMapper.insertSelective(admin);
    }

    @Override
    @Transactional
    public void updatePassWord(String userInfo, String passWord, String newPassWord) {
        Example example = new Example(Admin.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("userName", userInfo);
        Admin admin = adminMapper.selectOneByExample(example);
        if (admin == null) {
            throw new RuntimeException("用户不存在!");
        }
        //判断旧密码是否正确
        boolean matches = bCryptPasswordEncoder.matches(passWord, admin.getPassWord());
        if (!matches) {
            throw new RuntimeException("用户名或密码错误!");
        }
        //将新密码插入数据库
        admin.setPassWord(bCryptPasswordEncoder.encode(newPassWord));
        admin.setUpdateTime(new Date());
        adminMapper.updateByPrimaryKey(admin);
    }

    public Admin findByphone(String info) {
        Example example = new Example(Admin.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("mobile",info);
        Admin admin = adminMapper.selectOneByExample(example);
        return admin;
    }

    @Override
    @Transactional
    public void add(Map assignbody) {
        Admin admin = JSON.parseObject(JSON.toJSONString(assignbody), Admin.class);
        if ("男".equals((String) assignbody.get("genter")) || "1".equals((String) assignbody.get("avatar"))){
            admin.setGender("1");
        }else {
            admin.setGender("2");
        }
        admin.setUid(String.valueOf(idWorker.nextId()));
        admin.setUpdateTime(new Date());
        Role role = JSON.parseObject(JSON.toJSONString(assignbody.get("role")), Role.class);
        role.setUid(String.valueOf(idWorker.nextId()));
        adminMapper.insert(admin);
        roleMapper.insert(role);
    }

    @Override
    public Map assignByAdminUid(String adminUid) {
        List<Role> roles = roleMapper.selectAll();
        Admin admin = adminMapper.selectByPrimaryKey(adminUid);
        Map map = new HashMap();
        map.put("admin",admin);
        roles.forEach(role -> {
            if (role.getUid().equals(admin.getRoleUid())){
                map.put("assignedRoles",role);
            }
        });
        Role role = (Role) map.get("assignedRoles");
        roles.remove(role);
        map.put("unassignRoles",roles);
        return map;
    }

    @Override
    @Transactional
    public void delete(String[] adminUids) {
        for (String adminUid : adminUids) {
            adminMapper.deleteByPrimaryKey(adminUid);
        }
    }

    @Override
    public void edit(Map updateBody) {
        Admin admin = JSON.parseObject(JSON.toJSONString(updateBody), Admin.class);
        if ("男".equals((String) updateBody.get("genter")) || "1".equals((String) updateBody.get("avatar"))){
            admin.setGender("1");
        }else {
            admin.setGender("2");
        }
        admin.setUpdateTime(new Date());
        System.out.println(JSON.toJSONString(admin));
        int i = adminMapper.updateByPrimaryKeySelective(admin);
        if (i>0){
            System.out.println("管理员编辑成功");
        }else {
            throw new RuntimeException("管理员编辑失败");
        }
    }

    @Override
    public Map<String,Object> getList(String keyword, Long currentPage, Long pageSize) {
        PageHelper.startPage(currentPage.intValue(),pageSize.intValue());
        Example example = new Example(Admin.class);
        Example.Criteria criteria = example.createCriteria();
        if (keyword.contains("@")){
            criteria.andEqualTo("email",keyword);
        }
        if (checkCellphone(keyword)){
            criteria.andEqualTo("mobile",keyword);
        }
        if (keyword!=null && !"".equals(keyword)){
            criteria.andEqualTo("userName",keyword);
        }
        Page<Admin> admins = (Page<Admin>) adminMapper.selectByExample(example);
        List<Admin> list = new ArrayList<>();
        admins.forEach(admin -> {
            Role role = roleMapper.selectByPrimaryKey(admin.getRoleUid());
            admin.setRole(role);
            list.add(admin);
        });
        Map map =new HashMap();
        map.put("records",list);
        map.put("total",admins.getTotal());
        map.put("size",pageSize);
        map.put("orders",new ArrayList<>());
        map.put("current",currentPage);
        map.put("optimizeCountSql",true);
        map.put("isSearchCount",true);
        return map;
    }

    @Override
    public void restPassword(String uid) {
        String encode = bCryptPasswordEncoder.encode("123456");
        System.out.println(encode);
        adminMapper.restPassword(uid,encode);
    }

    //更改用户手机号或邮箱
    @Override
    public void updateEmail(String uid, String newInfo, String validCode) {
        Admin admin =new Admin();
        if (newInfo.contains("@")){
            admin.setEmail(newInfo);
        }
        if (checkCellphone(newInfo)){
            admin.setMobile(newInfo);
        }else {
            throw new RuntimeException("用户输入信息不为手机号或email");
        }
        admin.setUid(uid);
        admin.setValidCode(validCode);
        adminMapper.updateByPrimaryKeySelective(admin);
    }

    public static boolean checkCellphone(String cellphone) {
        String regex = "^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,1,2,5-9])|(177))\\d{8}$";
        Pattern pattern= Pattern.compile(regex);
        Matcher matcher=pattern.matcher(cellphone);
        return matcher.matches();
    }
}
